if (!Object.create) {
	Object.create = function(proto) {
		var F = function() {};
		F.prototype = proto;
		return new F();
	};
}

Number.prototype.random = function(y) {
	return Math.floor(Math.random() * (Math.abs(this - y) + 1)) + Math.min(this, y);
};

Function.prototype.extend = function(proto) {
	if (!proto) {
		proto = {};
	}
	var subclass = proto.hasOwnProperty("constructor") ? proto.constructor : proto.constructor = function() {};
	subclass.prototype = Object.create(this.prototype);
	for (var k in proto) {
		if (proto.hasOwnProperty(k)) {
			subclass.prototype[k] = proto[k];
		}
	}
	return subclass;
};

var JSEvent = Object.extend({
	constructor : function(type, detail) {
		this.type = String(type);
		if (arguments.length > 1) {
			this.detail = detail;
		}
	},
	detail : null,
	target : null,
	currentTarget : null,
	propagated : true,
	isPropagationStoped : function() {
		return !this.propagated;
	},
	stopPropagation : function() {
		if (this.propagated !== false) {
			this.propagated = false;
		}
	}
});

var JSEventListener = Object.extend({
	constructor : function(eventType, eventHandler) {
		this._eventType = String(eventType);
		this._eventHandler = eventHandler;
	},
	handleEvent : function(event) {
		if (!(event instanceof JSEvent)) {
			throw new TypeError("JSEventListener::handleEvent()");
		}
		if (!event.isPropagationStoped()) {
			this._eventHandler.call(event.currentTarget, event);
		}
	}
});

var JSEventTarget = Object.extend({
	constructor : function() {
		this._eventListeners = [];
	},
	addEventListener : function(eventType, eventHandler) {
		var eventListener;
		if (eventType instanceof JSEventListener) {
			eventListener = eventType;
			eventType = eventListener._eventType;
			eventHandler = eventListener._eventHandler;
		}
		eventType = String(eventType);
		var eventListeners = this._eventListeners;
		for (var i = 0; i < eventListeners.length; i++) {
			if (eventListeners[i]._eventType === eventType && eventListeners[i]._eventHandler === eventHandler) {
				return;
			}
		}
		if (!(eventListener instanceof JSEventListener)) {
			eventListener = new JSEventListener(eventType, eventHandler);
		}
		eventListeners.push(eventListener);
	},
	removeEventListener : function(eventType, eventHandler) {
		var eventListener;
		if (eventType instanceof JSEventListener) {
			eventListener = eventType;
			eventType = eventListener._eventType;
			eventHandler = eventListener._eventHandler;
		}
		eventType = String(eventType);
		var eventListeners = this._eventListeners;
		for (var i = 0; i < eventListeners.length; i++) {
			if (eventListeners[i]._eventType === eventType && eventListeners[i]._eventHandler === eventHandler) {
				eventListeners.splice(i, 1);
			}
		}
	},
	dispatchEvent : function(type, detail) {
		var event;
		if (type instanceof JSEvent) {
			event = type;
		} else if (arguments.length > 1) {
			event = new JSEvent(type, detail);
		} else {
			event = new JSEvent(type);
		}
		if (!event.target) {
			event.target = this;
		}
		var eventListeners = this._eventListeners;
		for (var i = 0; i < eventListeners.length; i++) {
			if (event.isPropagationStoped()) {
				break;
			}
			if (eventListeners[i]._eventType === event.type) {
				if (event.currentTarget !== this) {
					event.currentTarget = this;
				}
				eventListeners[i].handleEvent(event);
			}
		}
	}
});

if (!DOM) {
	var DOM = {};
}

DOM.XEvent = Object.extend({
	constructor : function(event) {
		
	}
});

DOM.XMouseEvent = DOM.XEvent.extend({
	constructor : function(event) {
		
	}
});

DOM.XKeyEvent = DOM.XEvent.extend({
	constructor : function(event) {
		
	}
});

DOM.addEventListener = function(node, type, eventHandler) {
	if (!node._eventListeners) {
		node._eventListeners = {};
	}
	if (!node._eventListeners[type]) {
		node._eventListeners[type] = [];
	}
	var eventListeners = node._eventListeners[type];
	for (var i = 0; i < eventListeners.length; i++) {
		if (eventListeners[i].eventHandler === eventHandler) {
			return;
		}
	}
	var xEventHandler = function(e) {
		if (!e) {
			e = window.event;
		}
		eventHandler.call(node, e);
	};
	if (node.addEventListener) {
		node.addEventListener(type, xEventHandler, false);
	} else if (node.attachEvent) {
		node.attachEvent("on" + type, xEventHandler);
	}
	eventListeners.push({
		eventHandler : eventHandler,
		xEventHandler : xEventHandler
	});
};

DOM.removeEventListener = function(node, type, eventHandler) {
	if (!node._eventListeners || !node._eventListeners[type]) {
		return;
	}
	var eventListeners = node._eventListeners[type];
	var xEventHandler;
	for (var i = 0; i < eventListeners.length; i++) {
		if (eventListeners[i].eventHandler === eventHandler) {
			xEventHandler = eventListeners[i].xEventHandler;
			if (node.removeEventListener) {
				node.removeEventListener(type, xEventHandler, false);
			} else if (node.detachEvent) {
				node.detachEvent("on" + type, xEventHandler);
			}
			eventListeners.splice(i, 1);
		}
	}
};

